package com.xiaochong.tir.manager.config.oss;


import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import com.xc.logclient.utils.LogTrace;
import com.xiaochong.service.common.config.oss.OSSConfig;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

/**
 * OSS简单文件上传工具类
 *
 * @author tanzhiwei
 * @date 2017年2月23日
 * @updateTime 2017年9月14日17:40:27
 */
@Component
public class OSSToolManage {

	/** 获取当前项目的文件夹路径 */
	public static String USER_DIR_URL = System.getProperty("user.dir");
	/** 获取当前项目所在文件夹路径 */
	public static String PROJECT_URL = new File(USER_DIR_URL).getParent();
	/** 获取当前项目的文件夹名称 */
	public static String PROJECT_NAME = new File(USER_DIR_URL).getName();

	@Autowired
	private OSSConfig ossConfig;

	/**
	 * 获取OSS实例化对象
	 *
	 * @return
	 */
	public OSSClient getOSSClient() {
		return new OSSClient(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
	}

	/**
	 * 获取OOS文件url，有读取有效期
	 *
	 * @param key
	 *            OOS文件key
	 * @param amount
	 *            有效时长，单位：小时
	 */
	public String getOSSUrl(String key, int amount) {
		// 判断传入key是否以OSS外网域名开头，如果是，去掉OSS外网域名开头
		if (key.indexOf(ossConfig.getEndpoint()) == 0) {
			key = key.substring(ossConfig.getEndpoint().length() + 1, key.length());
		}
		OSSClient ossClient = null;
		String urlStr = "";
		try {
			ossClient = getOSSClient();
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(new Date());
			calendar.add(Calendar.HOUR, amount);
			Date date = calendar.getTime();

			URL url = ossClient.generatePresignedUrl(ossConfig.getBucket(), key, date);
			urlStr = url.toString();
			urlStr.replaceAll("%2F", "/");
		} catch (Exception e) {
			LogTrace.error(e.getMessage(), e);
		} finally {
			ossClient.shutdown();
		}
		return urlStr;
	}

	/**
	 * 获取OOS文件url，读取有效期为2天
	 *
	 * @param key
	 *            OOS文件key
	 * @return
	 */
	public String getOSSUrl(String key) {
		return getOSSUrl(key, 24 * 2);
	}

	/**
	 * 本地文件上传
	 *
	 * @param diskPath
	 *            本地文件路径
	 * @param key
	 *            OOS文件key
	 * @return boolean
	 */
	public boolean upload(String diskPath, String key) {
		return upload(new File(diskPath), key);
	}

	/**
	 * 文件上传
	 *
	 * @param file
	 *            文件
	 * @param key
	 *            OOS文件key
	 * @return boolean
	 */
	public boolean upload(File file, String key) {
		OSSClient ossClient = null;
		boolean temp = false;
		try {
			ossClient = getOSSClient();
			PutObjectResult result = ossClient.putObject(ossConfig.getBucket(), key, file);
			temp = StringUtils.isNotBlank(result.getRequestId());
		} catch (Exception e) {
			LogTrace.error(e.getMessage(), e);
		} finally {
			ossClient.shutdown();
		}
		return temp;
	}

	/**
	 * 文件流上传
	 *
	 * @param inputStream
	 *            文件流
	 * @param key
	 *            OOS文件key
	 * @return boolean
	 */
	public boolean upload(InputStream inputStream, String key) {
		OSSClient ossClient = null;
		boolean temp = false;
		try {
			ossClient = getOSSClient();
			PutObjectResult result = ossClient.putObject(ossConfig.getBucket(), key, inputStream);
			temp = StringUtils.isNotBlank(result.getRequestId());
		} catch (Exception e) {
			LogTrace.error(e.getMessage(), e);
		} finally {
			ossClient.shutdown();
		}
		return temp;
	}
	
	/**
	 * 上传图片并且返回图片地址（传递文件类型InputStream）
	 *
	 * @param file
	 *            文件
	 * @param folder
	 *            文件夹路径
	 * @param fileName
	 *            文件名称
	 * @return
	 */
	 public String uploadImage(InputStream inputStream, String folder, String fileName) {
			String result = "";
			String key = folder + "/" + fileName;
			OSSClient ossClient = null;
			try {
				ossClient = getOSSClient();
				// 上传图片
				ossClient.putObject(ossConfig.getBucket(), key, inputStream);
				StringBuffer sf = new StringBuffer("");
				sf.append(ossConfig.getEndpoint().substring(0, 7));
                sf.append(ossConfig.getBucket()).append(".").append(ossConfig.getEndpoint().substring(7)).append("/").append(key);
				/*String imgurl = sf.append(ossConfig.getEndpoint()).append("/").append(folder).append("/").append(fileName)
						.toString();*/
				LogTrace.info("上传图片路径","imgurl", sf.toString());
				return sf.toString();
			} catch (Exception e) {
				LogTrace.error(e.getMessage(), e);
				result = "Error Message: " + e.getLocalizedMessage();
			} finally {
				ossClient.shutdown();
			}
			return result;
		}
	

	/**
	 * 上传图片并且返回图片地址（传递文件类型file）
	 *
	 * @param file
	 *            文件
	 * @param folder
	 *            文件夹路径
	 * @param fileName
	 *            文件名称
	 * @return
	 */
	public String uploadImage(File file, String folder, String fileName) {
		String result = "FAIL";
		String key = folder + "/" + fileName;
		OSSClient ossClient = null;
		try {
			ossClient = getOSSClient();
			// 上传图片
			ossClient.putObject(ossConfig.getBucket(), key, file);
			StringBuffer sf = new StringBuffer("");
			String imgurl = sf.append(ossConfig.getEndpoint()).append("/").append(folder).append("/").append(fileName)
					.toString();
			LogTrace.info("上传图片路径","imgurl", imgurl);
			return imgurl;
		} catch (Exception e) {
			LogTrace.error(e.getMessage(), e);
			result = "Error Message: " + e.getLocalizedMessage();
		} finally {
			ossClient.shutdown();
		}
		return result;
	}

	/**
	 * 删除阿里云服务器上的文件
	 *
	 * @param httpUrl
	 *            文件公网访问地址，前缀为http://oss.renrenhua.com
	 * @return
	 */
	public String delete(String httpUrl) {
		if (httpUrl != null && httpUrl.indexOf(ossConfig.getEndpoint()) == 0) {
			// 获取文件名
			String key = httpUrl.substring(ossConfig.getEndpoint().length() + 1, httpUrl.length());
			return deleteByKey(key);
		} else {
			return "URL不符合要求";
		}
	}

	/**
	 * 批量删除阿里云服务器上的文件
	 *
	 * @param httpUrls
	 *            文件公网访问地址，前缀为http://oss.renrenhua.com
	 * @return
	 */
	public String deletes(List<String> httpUrls) {
		List<String> keys = new ArrayList<>();
		for (String httpUrl : httpUrls) {
			if (httpUrl != null && httpUrl.indexOf(ossConfig.getEndpoint()) == 0) {
				// 获取OOS文件key
				String key = httpUrl.substring(ossConfig.getEndpoint().length() + 1, httpUrl.length());
				keys.add(key);
			}
		}
		return deleteByKeys(keys);
	}

	/**
	 * 删除阿里云服务器上的文件
	 *
	 * @param key
	 *            OOS文件key
	 * @return
	 */
	public String deleteByKey(String key) {
		OSSClient ossClient = null;
		try {
			ossClient = getOSSClient();
			// 判断服务器文件是否存在
			boolean found = ossClient.doesObjectExist(ossConfig.getBucket(), key);
			if (found) {
				// 删除服务器文件
				ossClient.deleteObject(ossConfig.getBucket(), key);
				return "删除成功！";
			} else {
				return "文件不存在！";
			}
		} catch (Exception e) {
			LogTrace.error(e.getMessage(), e);
		} finally {
			ossClient.shutdown();
		}
		return "删除失败！";
	}

	/**
	 * 批量删除阿里云服务器上的文件
	 *
	 * @param keys
	 *            OOS文件keys
	 * @return
	 */
	public String deleteByKeys(List<String> keys) {
		OSSClient ossClient = null;
		if (keys.size() > 1000) {
			return "删除数据过多！";
		}
		try {
			ossClient = getOSSClient();
			DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(ossConfig.getBucket());
			deleteObjectsRequest.setKeys(keys);
			ossClient.deleteObjects(deleteObjectsRequest);
			return "删除成功！";
		} catch (Exception e) {
			LogTrace.error(e.getMessage(), e);
		} finally {
			ossClient.shutdown();
		}
		return "删除失败！";
	}

	/**
	 * 获取OSS文件列表
	 *
	 * @param keyPrefix
	 *            文件夹前缀
	 * @return objects-文件列表（key-OSS文件key，value-文件上传时间 <br>
	 *         num-当前文件夹下有多少文件 <br>
	 *         size-当前文件夹的大小（单位：byte）
	 */
	public Map<String, Object> getObjects(String keyPrefix) {
		Map<String, Object> result = null;
		OSSClient ossClient = null;
		try {
			List<Map<String, Date>> objects = new ArrayList<>();
			ossClient = getOSSClient();
			ObjectListing objectListing;
			final int maxKeys = 1000;
			String nextMarker = null;
			int num = 0;
			long size = 0l;
			do {
				objectListing = ossClient.listObjects(new ListObjectsRequest(ossConfig.getBucket())
						.withPrefix(keyPrefix).withMarker(nextMarker).withMaxKeys(maxKeys));
				List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
				Map<String, Date> map = new HashMap<>();
				for (OSSObjectSummary s : sums) {
					map.put(s.getKey(), s.getLastModified());
					size += s.getSize();
					num++;
				}
				objects.add(map);
				nextMarker = objectListing.getNextMarker();
			} while (objectListing.isTruncated());
            HashMap<String, String> map = new HashMap<>();
            map.put("file_name",keyPrefix);
            map.put( "file_count",num+"");
            LogTrace.info("文件夹下文件个数 ",map);
			result = new HashMap<>();
			result.put("objects", objects);
			result.put("num", num);
			result.put("size", size);
			return result;
		} catch (Exception e) {
			LogTrace.error(e.getMessage(), e);
		} finally {
			ossClient.shutdown();
		}
		return result;
	}

	/**
	 * 下载OSS文件到项目所在目录的temp目录下
	 *
	 * @param key
	 *            OOS文件keys
	 * @return
	 */
	public boolean downObject(String key) {
		// 判断传入key是否以OSS外网域名开头，如果是，去掉OSS外网域名开头
		if (key.indexOf(ossConfig.getEndpoint()) == 0) {
			key = key.substring(ossConfig.getEndpoint().length() + 1, key.length());
		}
		OSSClient ossClient = null;
		try {
			ossClient = getOSSClient();
			// 获取文件名
			String objectName = key.substring(key.lastIndexOf("/") + 1, key.length());
			// 保存文件全路径
			String objectUrl = PROJECT_URL + "/temp/" + key;
			// 文件所在文件夹路径
			String folderUrl = objectUrl.substring(0, objectUrl.length() - objectName.length());
			// 判断文件夹是否存在，不存在创建
			File file = new File(folderUrl);
			if (!file.exists() && !file.isDirectory())
				file.mkdirs();
			ossClient.getObject(new GetObjectRequest(ossConfig.getBucket(), key), new File(objectUrl));
			return true;
		} catch (Exception e) {
			LogTrace.error(e.getMessage(), e);
		} finally {
			ossClient.shutdown();
		}
		return false;
	}
}
